;
(function (window, angular) {
    'use strict';
    var ybModule = angular.module("Service.ybModule", ['ajoslin.promise-tracker']);
    ybModule.config(['$httpProvider', function ($httpProvider) {
        if (!$httpProvider.defaults.headers.get) {
            $httpProvider.defaults.headers.get = {};
        }

        $httpProvider.defaults.headers.get['If-Modified-Since'] = 'Mon, 26 Jul 1997 05:00:00 GMT';
        $httpProvider.defaults.headers.get['Cache-Control'] = 'no-cache';
        $httpProvider.defaults.headers.get['Pragma'] = 'no-cache';
        $httpProvider.defaults.headers.common = {'x-from-site':window.AppData.config.otherData.sysSite};
        $httpProvider.defaults.useXDomain = true;
        $httpProvider.defaults.withCredentials = false;
        delete $httpProvider.defaults.headers.common['X-Requested-With'];
        $httpProvider.responseInterceptors.push('ybResponseInterceptor');
        $httpProvider.interceptors.push('ybRequestInjector');
    }]);
    ybModule.factory('ybResponseInterceptor', ['$window', '$filter', '$q', '$injector', 'securityRetryQueue', 'ybConfig', "$timeout", "$location",
        function ($window, $filter, $q, $injector, queue, ybConfig, $timeout, $location) {
        var jumpToLogin = false;
        return function (promise) {
            // Intercept failed requests
            return promise.then(function (response) {
                if (response.data.code == 2) {
                    $injector.get('ybHttp').CancelTracker();
                    if (jumpToLogin) {
                        return $q.reject(response);
                    }
                    // The request bounced because it was not authorized - add a new request to the retry queue
                    var retryPromise = queue.pushRetryFn('unauthorized-server', function retryRequest() {
                        // We must use $injector to get the $http service to prevent circular dependency
                        return $injector.get('$http')(response.config);
                    });

                    var queueLength = queue.getLength();
                    if (!jumpToLogin && queueLength == 1) {
                        $injector.get('UserContextService').Logout(true);
                        $injector.get('ybWidget').ShowLoginModal();//通过手动注入的方式防止循环依赖
                    }
                    return retryPromise;
                }
                if (response.data.SecAlg == 'Aes') {//若为AES加密则对响应报文解密
                    response.data.Value = JSON.parse($injector.get('SecurityUtil').AesDecrypt(response.data.Value));
                }
                return response;
            }, function (rejection) {
                var status = rejection.status;
                var errMsg = '';
                if (status === 0) {
                    errMsg = "网络出现未知的错误，请检查您的网络。"
                }
                if (status >= 300 && status < 400) {
                    errMsg = '请求被服务器重定向，状态码为' + status;
                }
                if (status >= 400 && status < 500) {
                    errMsg = '客户端出错，可能是发送的数据有误，状态码为' + status;
                }
                if (status >= 500) {
                    errMsg = '服务器发生错误，状态码为' + status;
                }

                errMsg += "<div class='table-word-break'>URL:" + rejection.config.url + '</div>';

                //$injector.get('ybWidget').ShowMessage( rejection.status + " " + rejection.statusText +":" +  rejection.config.url); ////通过手动注入的方式防止循环依赖
                $injector.get('ybWidget').ShowMessage(errMsg, $injector.get('MESG_TYPE').Error, {isHtml: true}); ////通过手动注入的方式防止循环依赖
                return $q.reject(rejection);
            });
        };
    }]);
    ybModule.factory("ybConfig", ["$q", "$log", function ($q, $log) {
        var _config;
        var _initConfig = function () {
            _config = window.AppData.config
        };
        return {
            getConfig: function () {
                return _config;
            },
            initConfig: _initConfig
        }
    }]);
    ybModule.factory("ybHttp", ["$rootScope", "$http", "$q", "ybConfig", "$location", "$state", "promiseTracker", function ($rootScope, $http, $q, ybConfig, $location, $state, promiseTracker) {
        $rootScope.loadingTracker = promiseTracker({activationDelay: 800});

        function _GetRequestUrl(serviceName, url) {
            var config = ybConfig.getConfig();
            return config.baseUrl.Site + config.serviceName[serviceName] + url;
        }

        function _Post(serviceName, url, formData) {
            var deferred = $q.defer();
            var needTracker = true;
            // if (url === "HumanBehavior/UpdateMenuCounter") {
            //     needTracker = false;
            // }
            var resp = $http.post(_GetRequestUrl(serviceName, url), formData, needTracker ? {tracker: $rootScope.loadingTracker} : {});
            resp.then(function (data, status, headers, config) {
                    deferred.resolve(data.data);
                },
                function (data, status, headers, config) {
                    deferred.reject({Code: data.status, Message: "服务器发生错误"});
                });
            return deferred.promise;
        }

        function _Get(serviceName, url, param) {
            var deferred = $q.defer();
            var resp = $http.get(_GetRequestUrl(serviceName, url), {
                params: param,
                tracker: $rootScope.loadingTracker
            }).then(function (data, status, headers, config) {
                    deferred.resolve(data.data);
                },
                function (data, status, headers, config) {
                    deferred.reject({Code: data.status, Message: "服务器发生错误"});
                });
            return deferred.promise;
        }
        function _Put(serviceName, url, formData) {
            var deferred = $q.defer();
            var needTracker = true;
            var resp = $http.put(_GetRequestUrl(serviceName, url), formData, needTracker?{tracker: $rootScope.loadingTracker}:{});
            resp.then(function (data, status, headers, config) {
                    /*todo:*/
                    deferred.resolve(data.data);
                },
                function (data, status, headers, config) {
                    deferred.reject({Code: status, Message: "服务器发生错误"});
                });
            return deferred.promise;
        }
        function _CancelTracker() {
            $rootScope.loadingTracker.cancel();
        }

        return {
            Post: _Post,
            Get: _Get,
            Put: _Put,
            RequestUrl: _GetRequestUrl,
            CancelTracker: _CancelTracker
        }
    }]);
    ybModule.service("EventBus", [function () {
        var subscriberList = [];

        function _subscribe(evt, fn) {
            for (var i = 0; i < subscriberList.length; ++i) {
                if (subscriberList[i].Event === evt && subscriberList[i].Fn === fn) {
                    return;
                }
            }
            subscriberList.push({Event: evt, Fn: fn});
        }

        function _unsubscribe(evt, fn) {

            for (var i = 0; i < subscriberList.length; ++i) {
                if (subscriberList[i].Event === evt && subscriberList[i].Fn === fn) {
                    break;
                }
            }
            subscriberList.splice(i, 1);

        }

        function _publish(evt, data) {
            var result = null;
            for (var i = 0; i < subscriberList.length; ++i) {
                if (subscriberList[i].Event === evt) {
                    result = subscriberList[i].Fn(data);
                }
            }
            return result;
        }

        return {
            Subscribe: _subscribe,
            Unsubscribe: _unsubscribe,
            Publish: _publish
        };
    }]);
    ybModule.factory("ybNavigator", ["$injector", "MESG_TYPE", function ($injector,MESG_TYPE) {
        function _fnIsIE8Browser() {
            if (navigator.appName == "Microsoft Internet Explorer" && navigator.appVersion.split(";")[1].replace(/[ ]/g, "") == "MSIE8.0") {
                return true;
            }
            return false;
        }

        function _fnIsIEBrowser() {
            if (!!window.ActiveXObject||'ActiveXObject' in window) {
                return true;
            }
            return false;
        }

        /**Parses string formatted as YYYY-MM-DD to a Date object.
         * If the supplied string does not match the format, an
         * invalid Date (value NaN) is returned.
         * @param {string} dateStringInRange format YYYY-MM-DD, with year in
         * range of 0000-9999, inclusive.
         * @return {Date} Date object representing the string.
         */
        function _fnParseNewDate(dateStringInRange) {
            var isoExp = /^\s*(\d{4})-(\d\d)-(\d\d)\s*$/,
                date = new Date(NaN), month,
                parts = isoExp.exec(dateStringInRange);

            if (parts) {
                month = +parts[2];
                date.setFullYear(parts[1], month - 1, parts[3]);
                if (month != date.getMonth() + 1) {
                    date.setTime(NaN);
                }
            }
            return date;
        }

        function _fnShowFlashHint(){
            if(angular.isUndefined(window.FileAPI.hasFlash) || window.FileAPI.hasFlash){
                return;
            }
            var content = "你的浏览器版本过低，需要安装<a href='https://get.adobe.com/flashplayer/?loc=cn' " +
                "target='_blank' class='danger-color' title='Adobe Flash Player'><span class='danger-color'>Adode Flash Player</span></a>" +
                "，如果已安装了，请确认Activex控件是否在浏览器启用，操作完成后请重新打开浏览器";
            $injector.get('ybWidget').ShowMessage(content, MESG_TYPE.ERROR, {isHtml:true});
        }

        return {
            IsIE8: _fnIsIE8Browser,
            ParseNewDate: _fnParseNewDate,
            ShowFlashHint: _fnShowFlashHint,
            IsIE: _fnIsIEBrowser
        }

    }])
    ybModule.factory('ybCacheData', ['$cacheFactory', function ($cacheFactory) {
        var cache = $cacheFactory('ybCacheData');
        return {
            save: function (key, data) {
                cache.put(key, data);
                return cache.info().size;
            },
            get: function (key) {
                var data = cache.get(key);
                if (!data) {
                    return null;
                }
                return data;
            },
            removeData: function (key) {
                cache.remove(key);
            },
            clearData: function () {
                cache.removeAll();
            }
        };

    }]);
    ybModule.factory('ybStateData', ['$cacheFactory', '$state', function ($cacheFactory, $state) {
        var cache = $cacheFactory('ybStateData');
        return {
            setData: function (key, data) {
                cache.put(key, data);
                return cache.info().size;
            },
            getData: function (key) {
                var data = cache.get(key);
                if (!data) {
                    return null;
                }
                return data;
            },
            removeData: function (stateName) {
                cache.remove(stateName);
            },
            clearData: function () {
                cache.removeAll();
            },
            pushData: function (prevState, key, val) {
                var prevObj = cache.get(prevState);
                if (!prevObj) {
                    return false;
                }
                prevObj[key] = val;
                return true;
            },
            /**
             * 缓存当前路由的状态
             * @param data(*Any) 需要缓存的状态数据
             * @param fromState(*String) *缓存的加载条件-前一个路由
             * @returns size(Integer)
             */
            setDataAndState: function (data, fromState) {
                var stateName = $state.current.name;
                cache.put(stateName, data);
                cache.put(stateName+"_PREV", fromState);
                return cache.info().size;
            },
            /**
             * 验证加载条件并获取当前路由的缓存
             * @param fromState(String;default:$state.params.fromState) 待验证的前一个路由名字
             * @returns data(Any)
             */
            validStateAndGetData: function (fromState) {
                fromState = fromState || $state.params.fromState;
                if(cache.get($state.current.name+"_PREV") != fromState){
                    return null;
                }
                var data = cache.get($state.current.name);
                if (!data) {
                    return null;
                }
                this.removeData($state.current.name);
                this.removeData($state.current.name+"_PREV");

                return data;
            }
        };
    }]);
    ybModule.factory('ybRequestInjector', ["$q", "$injector", "$filter", function ($q, $injector, $filter) {
        return {
            request: function (config) {
                if (config.method == 'POST') {
                    if ($injector.get('SecurityUtil').CheckEnable()) {
                        var timestamp = Date.parse(new Date()) / 1000; //正常代码:获取1970年01月01日00分00秒至今的总秒数
                        // var timestamp=1482462399967; //测试-复现重放攻击
                        if (!config.data) {
                            config.data = '';
                        }
                        else {
                            var requestParam = angular.fromJson(config.data);
                            if (requestParam.EncryptType == 'Aes') {
                                delete requestParam.EncryptType;
                                config.data = {EncryptMsg: $injector.get('SecurityUtil').AesEncrypt(JSON.stringify(requestParam))};
                                config.headers["X-EncryptType"] = "Aes";
                                config.headers["X-IntegrityHash"] = $injector.get('SecurityUtil').HmacSha1Sign(config.data.EncryptMsg + timestamp);
                            } else {
                                config.headers["X-IntegrityHash"] = $injector.get('SecurityUtil').HmacSha1Sign(JSON.stringify(config.data) + timestamp);
                            }
                            config.headers["X-Timestamp"] = timestamp;
                        }
                    }
                }
                config.headers["SC-AUTH"] = localStorage.getItem("ScAuthM");
                return config;
            }
        };
    }]);
})(window, window.angular);